﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using QLTT.Models;
using QLTT.Commands;
using System.Windows.Input;

namespace QLTT.ViewModels
{
    class AllClassViewModel : WorkspaceViewModel
    {
        private ObservableCollection<ClassViewModel> _lstClassViewModel;
        private icanDataContext _dataContext;
        private DelegateCommand _findCommand;
        private DelegateCommand _addCommand;
        private DelegateCommand _deleteCommand;
        private DelegateCommand _showClassAbsenceCommand;
        private DelegateCommand _showClassStudentCommand;
        private DelegateCommand _showClassMarkCommand;
        private IQueryable<ClassViewModel> _query;
        private string _className;
        public AllClassViewModel(icanDataContext dataContext)
        {
            _lstClassViewModel = new ObservableCollection<ClassViewModel>();
            _dataContext = dataContext;
            this.Level = 0;
            this.Room = 0;
            this.Teacher = 0;
            this.ClassTime = 0;
            this.Status = Properties.Resources.Combo_AllClass_Status_InProgressOrNotYetStart;
            base.DisplayName = Properties.Resources.Base_DisplayName_AllClass;
        }
        public AllClassViewModel(icanDataContext dataContext, bool isGetAll)
        {
            _lstClassViewModel = new ObservableCollection<ClassViewModel>();
            _dataContext = dataContext;
            if (isGetAll)
            {
                _query = _dataContext.Classes.Where(oClass => oClass.EndDate>=DateTime.Today).OrderByDescending(oClass => oClass.StartDate).Select(oClass => new ClassViewModel(_dataContext, oClass));
                this.NumRow = _query.Count();
                this.CurPage = 1;
                this.UpdateList();
            }
            this.Level = 0;
            this.Room = 0;
            this.Teacher = 0;
            this.ClassTime = 0;
            this.Status = Properties.Resources.Combo_AllClass_Status_InProgressOrNotYetStart;
            base.DisplayName = Properties.Resources.Base_DisplayName_AllClass;
        }
        public string Name
        {
            get { return _className; }
            set { _className = value; }
        }
        public long Level { get; set; }
        public long Room { get; set; }
        public long Teacher { get; set; }
        public string Status { get; set; }
        public long ClassTime { get; set; }
        public DateTime StartDate { get; set; }
        public List<LevelViewModel> Levels
        {
            get
            {
                List<LevelViewModel> lstLevel = _dataContext.Levels.Select(lv => new LevelViewModel(_dataContext, lv)).ToList();
                LevelViewModel lvm = new LevelViewModel(_dataContext);
                lvm.Name = QLTT.Properties.Resources.Combo_AllClass_Level_Default;
                lstLevel.Insert(0, lvm);
                return lstLevel;
                //return new ObservableCollection<LevelViewModel>(lstLevel);
            }
        }
        public List<TeacherViewModel> Teachers
        {
            get
            {
                List<TeacherViewModel> lstTeacher = _dataContext.Teachers.Select(t => new TeacherViewModel(_dataContext, t)).ToList();
                TeacherViewModel tm = new TeacherViewModel(_dataContext);
                tm.Name = QLTT.Properties.Resources.Combo_AllClass_Teacher_Default;
                lstTeacher.Insert(0, tm);
                return lstTeacher;
            }
        }
        public List<RoomViewModel> Rooms
        {
            get
            {
                List<RoomViewModel> lstRoom = _dataContext.Rooms.Select(r => new RoomViewModel(_dataContext, r)).ToList();
                RoomViewModel rVM = new RoomViewModel(_dataContext);
                rVM.Name = QLTT.Properties.Resources.Combo_AllClass_Room_Default;
                lstRoom.Insert(0, rVM);
                return lstRoom;
            }
        }
        public List<ClassTimeViewModel> ClassTimes
        {
            get
            {
                List<ClassTimeViewModel> lstClassTime = _dataContext.ClassTimes.Select(ct => new ClassTimeViewModel(_dataContext, ct)).ToList();
                ClassTimeViewModel rVM = new ClassTimeViewModel(_dataContext);
                lstClassTime.Insert(0, rVM);
                return lstClassTime;
            }
        }
        public string[] Statuses
        {
            get
            {
                return new string[]
                {
                    Properties.Resources.Combo_AllClass_Status_InProgressOrNotYetStart,
                    Properties.Resources.Combo_AllClass_Stutus_InProgress,
                    Properties.Resources.Combo_AllClass_Status_NotYetStart,
                    Properties.Resources.Combo_AllClass_Status_Finished,
                    Properties.Resources.Combo_AllClass_Status_InProgressOrFinished,
                    Properties.Resources.Combo_AllClass_Status_Default
                    
                };
            }
        }
        public ObservableCollection<ClassViewModel> AllClasss
        {
            get { return _lstClassViewModel; }
            set {
                _lstClassViewModel = value;
                base.OnPropertyChanged("AllClasss");
            }
        }
        public ICommand FindCommand
        {
            get
            {
                if (_findCommand == null)
                {
                    _findCommand = new DelegateCommand(Find);
                }
                return _findCommand;
            }
        }
        public ICommand AddCommand
        {
            get
            {
                if (_addCommand == null)
                {
                    _addCommand = new DelegateCommand(AddClass);
                }
                return _addCommand;
            }
        }
        public ICommand DeleteCommand
        {
            get
            {
                if (_deleteCommand == null)
                {
                    _deleteCommand = new DelegateCommand(DeleteClass, CanDelete);
                }
                return _deleteCommand;
            }
        }
        public ICommand ShowClassAbsenceCommand
        {
            get
            {
                if (_showClassAbsenceCommand == null)
                {
                    _showClassAbsenceCommand = new DelegateCommand(ShowClassAbsence, IsItemSelected);
                }
                return _showClassAbsenceCommand;
            }
        }
        public ICommand ShowClassStudentCommand
        {
            get
            {
                if (_showClassStudentCommand == null)
                {
                    _showClassStudentCommand = new DelegateCommand(ShowClassStudent, IsItemSelected);
                }
                return _showClassStudentCommand;
            }
        }
        public ICommand ShowClassMarkCommand
        {
            get
            {
                if (_showClassMarkCommand == null)
                {
                    _showClassMarkCommand = new DelegateCommand(ShowClassMark, IsItemSelected);
                }
                return _showClassMarkCommand;
            }
        }
        
        public void Find()
        {
            IQueryable<Class> myQuery = _dataContext.Classes;
            if (!string.IsNullOrEmpty(_className))
                myQuery = myQuery.Where<Class>(oClass => oClass.Name.ToLower().Contains(_className.ToLower()));
            //Add more Where Conditions here
            if(this.Level > 0)
                myQuery = myQuery.Where<Class>(oClass => oClass.Level == this.Level);
            if (this.Teacher > 0)
            {
                var query = from s in _dataContext.Schedules where s.Teacher == this.Teacher select s.Class;
                List<long> lstIDs = query.ToList();
                myQuery = myQuery.Where<Class>(oClass => lstIDs.Contains(oClass.ID));
            }
            if(this.Room > 0)
                myQuery = myQuery.Where<Class>(oClass => oClass.Room == this.Room);
            if (this.ClassTime > 0)
            {
                myQuery = myQuery.Where(oClass => oClass.Schedules.Where(s => s.ClassTime == this.ClassTime).ToList().Count > 0);
            }
            if (this.Status != Properties.Resources.Combo_AllClass_Status_Default)
            {
                if(this.Status == Properties.Resources.Combo_AllClass_Status_InProgressOrNotYetStart)
                {
                    myQuery = myQuery.Where(oClass => oClass.EndDate >= DateTime.Today);
                }else if(this.Status == Properties.Resources.Combo_AllClass_Stutus_InProgress)
                {
                    myQuery = myQuery.Where(oClass => oClass.EndDate >= DateTime.Today && oClass.StartDate <= DateTime.Today);
                }
                else if (this.Status == Properties.Resources.Combo_AllClass_Status_NotYetStart)
                {
                    myQuery = myQuery.Where(oClass => oClass.StartDate > DateTime.Today);
                }
                else if (this.Status == Properties.Resources.Combo_AllClass_Status_InProgressOrFinished)
                {
                    myQuery = myQuery.Where(oClass => oClass.StartDate<DateTime.Today);
                }
                else if (this.Status == Properties.Resources.Combo_AllClass_Status_Finished)
                {
                    myQuery = myQuery.Where(oClass => oClass.EndDate < DateTime.Today);
                }
            }
            //Order
            myQuery = myQuery.OrderByDescending(oClass => oClass.StartDate);
            //Select
            _query = myQuery.Select(oClass => new ClassViewModel(_dataContext, oClass));
            this.NumRow = _query.Count();
            //Reset to page 0
            this.CurPage = 1;
            this.UpdateList();
        }
        
        public void AddClass()
        {
            ClassViewModel ws = new ClassViewModel(_dataContext);
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, ws);
        }
        
        private void DeleteClass()
        {
            foreach (ClassViewModel tvm in AllClasss)
            {
                if (tvm.IsSelected)
                {
                    tvm.Delete();
                }
            }
            this.NumRow = _query.Count();
            this.UpdateList();

        }
        public void ShowClassAbsence()
        {
            ClassViewModel cVM = AllClasss.FirstOrDefault(c => c.IsSelected == true);
            if (cVM == null)
                return;
            ClassAbsenceViewModel ws = new ClassAbsenceViewModel(_dataContext, cVM.ID);
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, ws);
        }
        public void ShowClassStudent()
        {
            ClassViewModel cVM = AllClasss.FirstOrDefault(c => c.IsSelected == true);
            if (cVM == null)
                return;
            AllStudentViewModel ws = new AllStudentViewModel(_dataContext,cVM.ID);
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, ws);
        }
        public void ShowClassMark()
        {
            ClassViewModel cVM = AllClasss.FirstOrDefault(c => c.IsSelected == true);
            if (cVM == null)
                return;
            ClassMarkViewModel ws = new ClassMarkViewModel(_dataContext, cVM.ID);
            Mediator.NotifyColleagues<WorkspaceViewModel>(Messages.WorkspaceAdd, ws);
        }
        private bool IsItemSelected()
        {
            return AllClasss.Count(c => c.IsSelected == true) > 0;
        }
        private bool CanDelete()
        {
            if (ViewModelBase.CurrentRole!=UserRole.Administrator ||!IsItemSelected())
                return false;
            ClassViewModel cVM = AllClasss.FirstOrDefault(c => c.IsSelected == true);
            return cVM.CanDelete();
        }
        
        [MediatorLib.MediatorMessageSink(Messages.ListClassUpdated, ParameterType = typeof(Class))]
        public void UpdateListClass(Class oClass)
        {
            this.NumRow = _query.Count();
            this.UpdateList();
        }

        public override void UpdateList()
        {
            List<ClassViewModel> lstClasss = _query.Skip((this.CurPage - 1) * this.RowsPerPage).Take(this.RowsPerPage).ToList();
            AllClasss = new ObservableCollection<ClassViewModel>(lstClasss);
            base.UpdateList();
        }
    }
}

